using System;
using System.Collections.Generic;
using System.Text;
using SharpMud.Extensibility.Metadata.Requirements;

namespace SharpMud.Extensibility.Metadata
{
    /// <summary>
    /// Used to indicate that a given class is used to implement a specific base for a hosting object
    /// </summary>
    [AttributeUsage(AttributeTargets.Struct)]
    public class ExtensionAttribute : System.Attribute
    {
        #region Private Variables
            private Type _CastAs;
            private IExtensionRequirement[] _Requirements;
        #endregion

        #region Constructors
        private ExtensionAttribute() { }

        public ExtensionAttribute(System.Type castAs)
            : this(castAs, new IExtensionRequirement[] { })
        {
        }
        public ExtensionAttribute(string castAsType)
            : this(System.Type.GetType(castAsType,true,true))
        {
        }
        public ExtensionAttribute(string castAsType, params IExtensionRequirement[] requirements)
            : this(System.Type.GetType(castAsType, true, true), requirements)
        {
        }
        public ExtensionAttribute(System.Type castAs, params IExtensionRequirement[] requirements)
            : this()
        {
            if (castAs == null)
                throw new ArgumentNullException("castAs");
            if (requirements == null)
                throw new ArgumentNullException("requirements");
            _CastAs = castAs;
            _Requirements = requirements;
        }
        #endregion

        /// <summary>
        /// Determines if this given metadata about an extension is valid for a class that this instance of this attribute might be assigned to.
        /// </summary>
        /// <remarks>Specifcally, checks if the given type can be cast to the type that this metadata instance says that the extension is.</remarks>
        public bool IsValidAssignmentTo(System.Type potentialExtensionImplementor)
        {
            if (!IsImplementableType(_CastAs))
                return false;
            
            if (this._CastAs.IsAssignableFrom(potentialExtensionImplementor))
                return true;
            else
                return false;
        }

        #region Static Methods
        public static bool IsImplementableType(System.Type t)
        {
            if (t.IsSealed)
                return false;
            else
                return true;
        }
        #endregion
    }
}
